package com.baseweb.webadmin.controller.wx;

import com.baseweb.webadmin.controller.BaseController;
import com.baseweb.webadmin.controller.admin.LoginController;
import com.baseweb.webadmin.core.constants.*;
import com.baseweb.webadmin.core.model.bvo.*;
import com.baseweb.webadmin.core.model.pojo.*;
import com.baseweb.webadmin.core.util.*;
import com.baseweb.webadmin.service.ContentService;
import com.baseweb.webadmin.service.RoleService;
import com.baseweb.webadmin.service.UserOrderService;
import com.baseweb.webadmin.service.UserService;
import com.baseweb.webadmin.weixin.utils.Constant;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import weixin.popular.api.PayMchAPI;
import weixin.popular.api.SnsAPI;
import weixin.popular.api.TokenAPI;
import weixin.popular.api.UserAPI;
import weixin.popular.bean.paymch.*;
import weixin.popular.bean.sns.SnsToken;
import weixin.popular.bean.token.Token;
import weixin.popular.support.ExpireKey;
import weixin.popular.support.expirekey.DefaultExpireKey;
import weixin.popular.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;

@Controller
@RequestMapping(value = "/weixin/")
public class WechatController extends BaseController {

    private Logger log = LoggerFactory.getLogger(WechatController.class);

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserService userService;

    @Autowired
    private ContentService contentService;

    @Autowired
    private UserOrderService userOrderService;

    private String PREFIX = "/weixin/";

    //重复通知过滤
    private static ExpireKey expireKey = new DefaultExpireKey();

    /**
     * 数据流输出
     * @param outputStream
     * @param text
     * @return
     */
    private boolean outputStreamWrite(OutputStream outputStream, String text){
        try {
            outputStream.write(text.getBytes("utf-8"));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private weixin.popular.bean.user.User getWXUser(){
        Token token = TokenAPI.token(WeixinUtil.appId, WeixinUtil.appSecret);
//        return UserAPI.userInfo(token, )
        return null;
    }

    @RequestMapping(value = "/MP_verify_2RibNRia77ae8FT9")
    public void MP_verify(HttpServletRequest request,
                          HttpServletResponse response) {

        try {
            response.getWriter().print("2RibNRia77ae8FT9");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/auth", method = RequestMethod.GET)
    public void auth(@RequestParam(value = "signature", required = false) String signature,
                     @RequestParam(value = "timestamp", required = false) String timestamp,
                     @RequestParam(value = "nonce", required = false) String nonce,
                     @RequestParam(value = "echostr", required = false) String echostr,
                    HttpServletRequest request,
                     HttpServletResponse response) {

        //验证请求签名
        if(!signature.equals(SignatureUtil.generateEventMessageSignature(WeixinUtil.token,timestamp,nonce))){
            log.info("The request signature is invalid");
            return;
        }

        //首次请求申请验证,返回echostr
        if(echostr!=null){
            try {
                outputStreamWrite(response.getOutputStream(),echostr);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
    }

    @RequestMapping(value = "/index")
    public String index(Model model) {

        List<ByAd> adList = contentService.selectAdListByPage(AdPositionType.INDEX_LUNBO.getCode(), BaseState.NORMAL.getCode(), 0, 10);
        model.addAttribute("adList", adList);

        List<ByAd> curList = contentService.selectAdListByPage(AdPositionType.CURRENT_RECOMMEND.getCode(), BaseState.NORMAL.getCode(), 0, 8);
        model.addAttribute("curList", curList);

        return PREFIX +"index";
    }

    @RequestMapping(value = "/biz_channel")
    public String biz_channel(@RequestParam(value = "position_id", required = false) Integer position_id,
                           @RequestParam(value = "channel_id", required = false) Integer channel_id,
                           Model model) {

        List<ByChannel> leftSubList = contentService.selectChannelListByPage(position_id, channel_id, BaseState.NORMAL.getCode(), 0, Integer.MAX_VALUE);

        model.addAttribute("leftSubList", leftSubList);

        return PREFIX +"biz_channel";
    }

    @RequestMapping(value = "/biz_list")
    public String biz_list(@RequestParam(value = "channel_id", required = false) Integer channel_id,
                           @RequestParam(value = "page", defaultValue = "1") Integer page,
                           @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize,

                           Model model) {

//        List<User> bizList = userService.selectBizUserListByPage(null,channel_id,null,null,null,null,(page-1)*pageSize, pageSize, null, null, null);
//        int total = userService.selectBizUserListCount(null,channel_id,null,null,null,null, null, null, null);


        List<UserInfoDetailBvo> list = new ArrayList<UserInfoDetailBvo>();
        List<User> bizList = userService.selectBizUserListByPage(null,null,channel_id,null,null,null,null,(page-1)*pageSize, pageSize, BaseState.NORMAL.getCode(), null, null,null);
        int total = userService.selectBizUserListCount(null,null,channel_id,null,null,null,null, BaseState.NORMAL.getCode(), null, null);


        if (bizList != null && bizList.size() > 0){
            for (User current : bizList){
                List<ByUserBizProduct> productList = userService.selectProductListByPage(current.getId(), null, null,0, 4,
                        null, null, null, null, BaseState.NORMAL.getCode());
                List<ByUserBizAuth> authList = userService.selectBizVerifyListByPage(current.getId(), null, null,0, 4, BaseState.NORMAL.getCode());
                UserInfoDetailBvo bvo = UserInfoDetailBvo.copyFrom(current, productList, authList, contentService.findChannel(current.getBizWorkType()));

                list.add(bvo);
            }
        }

        model.addAttribute("bizList", list);
        model.addAttribute("total", total);

        int totalPage = total/pageSize;
        int tmpDiv = total%pageSize;
        if (tmpDiv > 0){
            totalPage +=1;
        }
        model.addAttribute("totalPage", totalPage);

        model.addAttribute("currentPage", page);
        model.addAttribute("pageSize", pageSize);

        model.addAttribute("channel_id", channel_id);

        return PREFIX +"biz_list";
    }

    @RequestMapping(value = "/biz_index")
    public String biz_index(@RequestParam(value = "user_id", required = false) Integer user_id,
                            Model model) {

//        List<ByChannel> topList = contentService.selectChannelListByPage(ChannelType.TOP_CHANNEL.getCode(), 0, 0, 6);
//        model.addAttribute("topList", topList);
//
//        User user = userService.selectUserById(user_id);
//        model.addAttribute("user", user);
//
//        List<ByUserBizAuth> authList = userService.selectBizVerifyListByPage(user.getId(), null, null, 0,3);
//        model.addAttribute("authList", authList);
//
//        List<ByUserBizProduct> productList = userService.selectProductListByPage(user.getId(), null, null, 0, 6,null,null,null,null);
//        model.addAttribute("productList", productList);

        List<ByChannel> topList = contentService.selectChannelListByPage(ChannelType.TOP_CHANNEL.getCode(), 0, BaseState.NORMAL.getCode(), 0, 6);
        model.addAttribute("topList", topList);

//        List<ByUserBizProduct> productList = userService.selectProductListByPage(null, product_type, channel_id,(page-1)*pageSize, pageSize,
//                sort, style_type, price, keyword);
//        int total = userService.selectProductListCount(null, product_type, channel_id,sort, style_type, price, keyword);
//
//        model.addAttribute("productList", productList);
//        model.addAttribute("total", total);
//        model.addAttribute("pageSize", pageSize);

        User user = userService.selectUserById(user_id);
        model.addAttribute("user", user);

        ByChannel channel = contentService.findChannel(user.getBizWorkType());
        model.addAttribute("channel", channel);

        List<ByUserBizAuth> authList = userService.selectBizVerifyListByPage(user.getId(), null, null, 0,5, BaseState.NORMAL.getCode());
        model.addAttribute("authList", authList);

        List<ByUserBizProduct> productList = userService.selectProductListByPage(user.getId(), null, null, 0, 6,null,null,null,null, BaseState.NORMAL.getCode());
        model.addAttribute("productList", productList);

        List<ByUserExample> exampleList = userService.selectExampleListByPage(user.getId(), BaseState.NORMAL.getCode(), null, 0, 8);
        model.addAttribute("exampleList", exampleList);


        //开通城市
        Map<String, List<String>> openCitiesMap = new HashMap<String, List<String>>();
        List<ByOpenCity> opencities = userService.selectAllCitiesObjectList(user.getId());
        if (opencities !=null && opencities.size() > 0){
            Set provinceSet = new HashSet();

            for (ByOpenCity current : opencities){
                if (!provinceSet.contains(current.getProvince())){
                    List<String> tmpCities = new ArrayList<String>();
                    openCitiesMap.put(current.getProvince(), tmpCities);
                    provinceSet.add(current.getProvince());
                }
            }
            model.addAttribute("openProvinces", new ArrayList<String>(provinceSet));

            Set citiesSet = new HashSet();
            for (ByOpenCity current : opencities){
                if (!citiesSet.contains(current.getCity())){
                    List<String> tmpCities = openCitiesMap.get(current.getProvince());
                    tmpCities.add(current.getCity());
                    citiesSet.add(current.getCity());
                }
            }
        }
        model.addAttribute("openCitiesMap", openCitiesMap);


        //评论
//        List<ByUserOrderDetail> detailList = userOrderService.selectOrderDetailListByPage(user_id, null, 0, Integer.MAX_VALUE);
//        List<OrderCommentBvo> detailBvoList = new ArrayList<OrderCommentBvo>();
//        if (detailList != null && detailList.size() > 0){
//            for (ByUserOrderDetail current : detailList){
//                OrderCommentBvo bvo = OrderCommentBvo.copyFrom(current, userService.selectUserById(current.getUserId()));
//                detailBvoList.add(bvo);
//            }
//        }

        List<ByUserOrder> commentList = userOrderService.selectOrderListByBizUser(null, user_id, OrderStatus.CONFIRM_ORDER.getCode(), null,0, Integer.MAX_VALUE);

        List<OrderCommentBvo> detailBvoList = new ArrayList<OrderCommentBvo>();
        if (commentList != null && commentList.size() > 0){
            for (ByUserOrder current : commentList){
                OrderCommentBvo bvo = OrderCommentBvo.copyFrom(current, userService.selectUserById(current.getUserId()));
                detailBvoList.add(bvo);
            }
        }
        model.addAttribute("commentList", detailBvoList);


        //档期
//        List<ByUserBizSchedule> scheduleList = userOrderService.selectScheduleListByPage(user_id,null,0,Integer.MAX_VALUE);
//        model.addAttribute("scheduleList",scheduleList);

        Map<String, String> scheduleData = userOrderService.getUserScheduleListView(user_id, 0, 0);

        if (scheduleData != null && scheduleData.keySet().size() > 0) {
            try {
                model.addAttribute("scheduleData", new ObjectMapper().writeValueAsString(scheduleData));
            } catch (IOException e) {
                model.addAttribute("scheduleData", "");
                e.printStackTrace();
            }
        }else{
            model.addAttribute("scheduleData", "");
        }

        //信誉
        String creditStr = CommonUtil.getBizCreditFlag(user.getBizDealCount());
        if (StringUtils.isNotBlank(creditStr)) {
            model.addAttribute("creditData", creditStr);
        }

        return PREFIX + "biz_index";
    }



    @RequestMapping(value = "/add_schedule_auth")
    public String add_schedule_auth(@RequestParam(value = "user_id", required = false) Integer user_id,
            Model model) {

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/add_schedule", true, ""+user_id);
    }

    @RequestMapping(value = "/add_schedule")
    public String add_schedule(@RequestParam(value = "code", required = false) String code,
                                @RequestParam(value = "state", required = false) String state,
                           Model model) {

        if (StringUtils.isBlank(code)){
            return null;
        }

        SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

        weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");

        User user = userService.selectUserByWxId(null, wxuser.getUnionid());

        if (user == null){
            return PREFIX + "me";
        }

        List<ByUserBizProduct> list = userService.selectProductListByPage(Integer.valueOf(state), null, null,0, Integer.MAX_VALUE,
                null, null, null, null,BaseState.NORMAL.getCode());

        model.addAttribute("productList", list);

        model.addAttribute("biz_user_id", state);

        model.addAttribute("user_id", user.getId());

        model.addAttribute("current_date", DateUtil.dateToString(new DateTime().plusDays(1)));

        return PREFIX +"add_schedule";
    }



    @RequestMapping(value = "/ad", method = RequestMethod.GET)
    public String ad(@RequestParam(value = "id", required = false) Integer id,
                     Model model) {

        if (id !=null && id > 0){
            ByAd byAd = contentService.findAd(id);
            model.addAttribute("ad", byAd);
        }

        return PREFIX + "ad";
    }

    @RequestMapping(value = "/me_auth")
    public String me_auth(Model model) {

//        return "redirect:/weixin/me";

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/me", true, null);
    }

    @RequestMapping(value = "/me")
    public String me(@RequestParam(value = "code", required = false) String code,
                     Model model) {
        if (StringUtils.isBlank(code)){
            return null;
        }
        SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

        weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");

        User user = userService.selectUserByWxId(null, wxuser.getUnionid());
        if (user != null){
            if (StringUtils.isBlank(user.getMobile())){
                return PREFIX +"update_me";
            }else{
                model.addAttribute("user", user);
                return PREFIX +"me";
            }
        }else{
            model.addAttribute("open_id", wxuser.getOpenid());
            model.addAttribute("nickname", wxuser.getNickname());
            model.addAttribute("union_id", wxuser.getUnionid());
            return PREFIX +"update_me";
        }
    }


    @RequestMapping(value = "/update_me")
    public String update_me(@RequestParam(value = "open_id", required = false) String open_id,
                            @RequestParam(value = "nickname", required = false) String nickname,
                            @RequestParam(value = "union_id", required = false) String union_id,
                            Model model) {

        model.addAttribute("open_id", open_id);
        model.addAttribute("nickname", nickname);
        model.addAttribute("union_id", union_id);

        return PREFIX +"update_me";
    }

    @RequestMapping(value = "/submitMe")
    public String submitMe( @RequestParam(value = "open_id", required = false) String open_id,
                           @RequestParam(value = "nickname", required = false) String nickname,
                           @RequestParam(value = "union_id", required = false) String union_id,
                            @RequestParam(value = "mobile", defaultValue = "") String mobile,
                           @RequestParam(value = "password", defaultValue = "") String password,
                           @RequestParam(value = "vcode", defaultValue = "") String vcode,
                        Model model) {

        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password) || StringUtils.isBlank(vcode)){
            model.addAttribute("result", "数据不能为空!");
            return PREFIX + "update_me";
        }

        /**
         * 手机号码和发送的手机验证码一致性验证
         */
        String result = CheckCodeUtil.verify(mobile, vcode);

        User user = null;
        if ("1".equalsIgnoreCase(result)) {
            user = userService.selectUserByWxId(null, union_id);

            if (user != null) {
                user.setMobile(mobile);
                user.setPassword(MD5Util.Md5(password.trim()));
                user.setUsername(mobile);
                user.setCnName(nickname);

                userService.updateUser(user);
            }else{
                user = userService.selectByName(mobile);
                if (user == null){
                    user = new User();

                    user.setWxOpenid(open_id);
                    user.setWxUnionid(union_id);
                    user.setCnName(nickname);

                    user.setMobile(mobile);
                    user.setPassword(MD5Util.Md5(password.trim()));
                    user.setUsername(mobile);
                    user.setUserType(UserType.NORMAL_USER.getCode());
                    user.setToken(MD5Util.Md5(RandCharUtil.getRandStr(10) + "boyi" + DateUtil.dateToString(new DateTime()) + RandCharUtil.getRandStr(8)));
//                user.setCnName("user-" + RandCharUtil.getRandStr(8));
                    user.setStatus(BaseState.NORMAL.getCode());
                    user.setCreateTime(new DateTime());
                    user.setUpdateTime(new DateTime());
                    user.setOrderCount(0);
                    user.setBizDealCount(0);
                    user.setCoins(50);
                    user.setIsHot(0);
                    user.setMoney(new BigDecimal("0.00"));
                    user.setLevelCoins(0);

                    userService.insertUser(user);

                    writeCoinsLog(user, CoinType.REGISTER.getCode(), 50);

                    //User currentUser = userService.selectByName(mobile);
                    if (user != null) {
                        UserRoleKey userRoleKey = new UserRoleKey();
                        userRoleKey.setRoleId(2);
                        userRoleKey.setUserId(user.getId());
                        roleService.insertUserRoleKey(userRoleKey);
                    }
                }else{
                    user.setWxOpenid(open_id);
                    user.setWxUnionid(union_id);
                    userService.updateUser(user);
                }
            }
        }else{
            model.addAttribute("result", "验证码不正确!");
            return PREFIX + "update_me";
        }

        model.addAttribute("user", user);

        return PREFIX +"me";
    }


    @RequestMapping(value = "/order_auth")
    public String order_auth(@RequestParam(value = "id", required = false) Integer id,
                        Model model) {

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/order", true, null);

    }

    @RequestMapping(value = "/order")
    public String order(@RequestParam(value = "code", required = false) String code,
//                        @RequestParam(value = "page", defaultValue = "1") Integer page,
//                        @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize,
                    Model model) {

        if (StringUtils.isBlank(code)){
            return null;
        }
        SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

        weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");

        User user = userService.selectUserByWxId(null, wxuser.getUnionid());

        if (user != null) {
            List<ByUserOrder> list = userOrderService.selectAllOrderListByPage(user.getId(), 0, Integer.MAX_VALUE);

            List<OrderBvo> orderBvos = new ArrayList<OrderBvo>();
            for (ByUserOrder current : list) {
                OrderBvo bvo = OrderBvo.copyFrom(current, userService.selectUserById(current.getUserId()), userService.selectUserById(current.getBizUserId()));
                orderBvos.add(bvo);
            }

            model.addAttribute("orderList", orderBvos);
        }

        model.addAttribute("user", user);

        return PREFIX +"order";
    }

    @RequestMapping(value = "/order_detail")
    public String order_detail(@RequestParam(value = "order_id", required = false) Integer order_id,
                        Model model) {

        if (order_id == null || order_id <= 0){
            model.addAttribute("result", "参数不正确!");
            return "redirect:"+PREFIX +"order_auth";
        }

        ByUserOrder byUserOrder = userOrderService.findByUserOrder(order_id);

        List<ByUserOrderDetail> list = userOrderService.selectOrderDetailListByPage(null, order_id,0, Integer.MAX_VALUE);
//        int total = userOrderService.selectOrderDetailListCount(user.getId(), order_id);

        List<ByUserOrderDetailInfoBvo> productList = new ArrayList<ByUserOrderDetailInfoBvo>();

        if (list != null && list.size() > 0){   //
            List<Integer> productIds = new ArrayList<Integer>();
            for(ByUserOrderDetail current : list){
                ByUserOrderDetailInfoBvo bvo = ByUserOrderDetailInfoBvo.copyFrom(current, userService.selectUserById(current.getUserId()), userService.selectUserById(current.getBizUserId()), userService.findBizProduct(current.getProductId()));
                productList.add(bvo);
            }

//            productList = userService.findBizProductList(productIds);
        }

        OrderWithDetailBvo bvo = OrderWithDetailBvo.copyFrom(OrderBvo.copyFrom(byUserOrder,
                userService.selectUserById(byUserOrder.getUserId()),
                userService.selectUserById(byUserOrder.getBizUserId())), productList);

        model.addAttribute("detail", bvo);

        return PREFIX +"order_detail";
    }




    @RequestMapping(value = "/pay_order")
    public String pay_order(@RequestParam(value = "order_id", required = false) Integer order_id,
                             Model model) {

        if (order_id == null || order_id <= 0){
            model.addAttribute("result", "参数不正确!");
            return "redirect:"+PREFIX +"order_detail?order_id="+order_id;
        }


//        Unifiedorder unifiedorder = new Unifiedorder();
//        unifiedorder.setAppid(WeixinUtil.appId);
//        unifiedorder.setMch_id(WeixinUtil.payMchId);
//        unifiedorder.setNonce_str(UUID.randomUUID().toString().toString().replace("-", ""));
//
//        unifiedorder.setOpenid(wx_openid);
//        unifiedorder.setBody("商品信息");
//        unifiedorder.setOut_trade_no("123456");
//        unifiedorder.setTotal_fee("1");//单位分
//        unifiedorder.setSpbill_create_ip(request.getRemoteAddr());//IP
//        unifiedorder.setNotify_url("http://mydomain.com/test/notify");
//        unifiedorder.setTrade_type("JSAPI");//JSAPI，NATIVE，APP，WAP
//        //统一下单，生成预支付订单
//        UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder,key);
//
//        //@since 2.8.5  API返回数据签名验证
//        if(unifiedorderResult.getSign_status() !=null && unifiedorderResult.getSign_status()){
//            String json = PayUtil.generateMchPayJsRequestJson(unifiedorderResult.getPrepay_id(), appid, key);
//
//            //将json 传到jsp 页面
//            request.setAttribute("json", json);
//            //示例jsp
//            request.getRequestDispatcher("pay_example.jsp").forward(request,response);
//        }


        return "redirect:"+PREFIX +"order_auth";
    }


    @RequestMapping(value = "/pay_notify")
    public String pay_notify(@RequestParam(value = "order_id", required = false) Integer order_id,
                               Model model) {

        if (order_id == null || order_id <= 0){
            model.addAttribute("result", "参数不正确!");
            return "redirect:"+PREFIX +"order_auth";
        }

//        //获取请求数据
//        String xmlData = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8"));
//        //将XML转为MAP,确保所有字段都参与签名验证
//        Map<String,String> mapData = XMLConverUtil.convertToMap(xmlData);
//        //转换数据对象
//        MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class,xmlData);
//        //已处理 去重
//        if(expireKey.exists(payNotify.getTransaction_id())){
//            MchBaseResult baseResult = new MchBaseResult();
//            baseResult.setReturn_code("SUCCESS");
//            baseResult.setReturn_msg("OK");
//            response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
//            return;
//        }
//        //签名验证
//        if(SignatureUtil.validateSign(mapData,key)){
//            //@since 2.8.5
//            payNotify.buildDynamicField(mapData);
//
//            expireKey.add(payNotify.getTransaction_id());
//            MchBaseResult baseResult = new MchBaseResult();
//            baseResult.setReturn_code("SUCCESS");
//            baseResult.setReturn_msg("OK");
//            response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
//        }else{
//            MchBaseResult baseResult = new MchBaseResult();
//            baseResult.setReturn_code("FAIL");
//            baseResult.setReturn_msg("ERROR");
//            response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
//        }

        return "redirect:"+PREFIX +"order_auth";
    }


























    @RequestMapping(value = "/addTrolley")
    public String addTrolley(@RequestParam(value = "user_id",required = false) Integer user_id,
                            @RequestParam(value = "product_id",required = false) Integer product_id,
                             @RequestParam(value = "biz_user_id",required = false) Integer biz_user_id,
                             @RequestParam(value = "schedule_date",required = false) String schedule_date,
                             @RequestParam(value = "dinner_type",required = false) String dinner_type,
                             @RequestParam(value = "amount",defaultValue = "1") Integer amount,
                               Model model) {

        if (product_id != null && product_id > 0) {
            ByUserTrolley byUserTrolley = new ByUserTrolley();
            byUserTrolley.setProductId(product_id);
            byUserTrolley.setUserId(user_id);
            if (product_id != null && product_id.intValue() > 0){
                if (biz_user_id != null && biz_user_id.intValue() > 0){
                    byUserTrolley.setBizUserId(biz_user_id);
                }else{
                    byUserTrolley.setBizUserId(userService.findBizProduct(product_id).getUserId());
                }
            }
            byUserTrolley.setScheduleDate(DateUtil.getDateTime(schedule_date));
            byUserTrolley.setDinnerType(dinner_type);
            byUserTrolley.setAmount(amount);
            byUserTrolley.setCreateTime(new DateTime());
            byUserTrolley.setUpdateTime(new DateTime());

            userService.insertTrolley(byUserTrolley);

        }

        return "redirect:"+PREFIX + "trolley_auth";
    }


    @RequestMapping(value = "/submitOrder_auth")
    public String submitOrder_auth(Model model) {

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/submitOrder", true, null);

    }

    @RequestMapping(value = "/submitOrder")
    public String submitOrder(@RequestParam(value = "code", required = false) String code,
                              RedirectAttributes redirectAttributes, Model model) {
        try{
            if (StringUtils.isBlank(code)){
                return null;
            }
            SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

            weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");

            User user = userService.selectUserByWxId(null, wxuser.getUnionid());

            List<ByUserTrolley> byUserTrolleys = userService.selectTrolleyListByPage(user.getId(), 0, Integer.MAX_VALUE);


            Map<Integer, List<ByUserTrolley>> tmpMap = new HashMap<Integer, List<ByUserTrolley>>();
            if (byUserTrolleys !=null && byUserTrolleys.size() > 0){
                Set set = new HashSet();

                for (ByUserTrolley current : byUserTrolleys){
                    if(set.contains(current.getBizUserId())){
                        tmpMap.get(current.getBizUserId()).add(current);
                    }else{
                        List<ByUserTrolley> tmpList = new ArrayList<ByUserTrolley>();
                        tmpList.add(current);
                        tmpMap.put(current.getBizUserId(), tmpList);

                        set.add(current.getBizUserId());
                    }
                }

                for(Iterator it = tmpMap.keySet().iterator(); it.hasNext();) {
                    Integer mKey = (Integer) it.next();
                    User currentBizUser = userService.selectUserById(mKey);

                    ByUserOrder order = new ByUserOrder();
                    order.setUserId(user.getId());

                    order.setPayType(PayType.WECHAT_PAY.getCode());
                    order.setPayStatus(OrderPayStatus.NOT_PAY.getCode());
                    order.setBizUserId(mKey);
                    order.setPrice(BigDecimal.ZERO);
                    order.setDeposit(BigDecimal.ZERO);
                    order.setNeedPayPrice(BigDecimal.ZERO);
                    order.setCreateTime(new DateTime());
                    order.setUpdateTime(new DateTime());

                    userOrderService.insertByUserOrder(order);

                    BigDecimal orderPrice = BigDecimal.ZERO;
                    for (ByUserTrolley current : tmpMap.get(mKey)){
                        ByUserBizProduct byUserBizProduct = userService.findBizProduct(current.getProductId());

                        ByUserOrderDetail detail = new ByUserOrderDetail();
                        detail.setOrderId(order.getId());

                        if(current.getAmount() == null || current.getAmount() < 1){
                            detail.setAmount(1);
                        }else{
                            detail.setAmount(current.getAmount());
                        }

                        detail.setUserId(user.getId());
                        detail.setProductId(current.getProductId());
                        detail.setPrice(byUserBizProduct.getCurrentPrice().multiply(new BigDecimal(current.getAmount())));

                        orderPrice = orderPrice.add(detail.getPrice());

                        detail.setScheduleDate(current.getScheduleDate());
                        detail.setDinnerType(current.getDinnerType());
                        detail.setBizUserId(byUserBizProduct.getUserId());
//                        detail.setOrderId(order.getId());
                        detail.setDeposit(Constants.PRODUCT_DEPOSIT_RATIO.multiply(detail.getPrice()));
                        detail.setCreateTime(new DateTime());
                        detail.setUpdateTime(new DateTime());
                        userOrderService.insertByUserOrderDetail(detail);

                        //add Schedule
                        ByUserBizSchedule byUserBizSchedule = new ByUserBizSchedule();
                        byUserBizSchedule.setUserId(current.getBizUserId());
                        byUserBizSchedule.setOrderBy(detail.getUserId());
                        byUserBizSchedule.setScheduleDate(detail.getScheduleDate());
                        byUserBizSchedule.setStatus(BaseState.NORMAL.getCode());
                        byUserBizSchedule.setScheduleType(ScheduleType.getByName(detail.getDinnerType()).getCode());
                        byUserBizSchedule.setCreateTime(new DateTime());
                        byUserBizSchedule.setUpdateTime(new DateTime());

                        userOrderService.insertSchedule(byUserBizSchedule);
                    }

                    ByUserOrder newOrder = userOrderService.findByUserOrder(order.getId());

                    //更新订单价格
                    newOrder.setPrice(orderPrice);
                    if (currentBizUser.getBizWorkType().intValue() == 1){ //策划师
                        newOrder.setStatus(OrderStatus.NEW_ORDER.getCode());
                    }else{
                        newOrder.setStatus(OrderStatus.VERIFY_ORDER.getCode());

                        //send msg
//                        Map<String, Object> map = new LinkedHashMap<String, Object>();
//                        map.put("code", ""+newOrder.getStatus());
//
//                        CommonUtil.sendMessage(currentBizUser.getMobile(), JSONObject
//                                .fromObject(map).toString(), ConfigUtil
//                                .getSms_template_code_new_order());
                    }
                    newOrder.setDeposit(Constants.PRODUCT_DEPOSIT_RATIO.multiply(newOrder.getPrice()));
                    newOrder.setNeedPayPrice(newOrder.getPrice().subtract(newOrder.getDeposit()));

                    userOrderService.insertByUserOrder(newOrder);
                }
            }

            userService.deleteTrolleyByUserAndProduct(user.getId(), null);

            model.addAttribute("result", true);
        }catch (Exception ex){
            ex.printStackTrace();
            model.addAttribute("result", false);
        }
//        redirectAttributes.addAttribute("message", "订单提交成功,请到后台查看!");
        redirectAttributes.addFlashAttribute("message", "订单提交成功,请到后台查看!");


//        RedirectView redirect = new RedirectView("/index");
//        redirect.setExposeModelAttributes(false);

        return "redirect:"+PREFIX+"order_auth";
    }

    @RequestMapping(value = "/trolley_auth")
    public String trolley_auth() {

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/trolley", true, null);
    }

    @RequestMapping(value = "/trolley")
    public String trolley(@RequestParam(value = "code", required = false) String code,
                          Model model) {

        if (StringUtils.isBlank(code)){
            return null;
        }
        SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

        weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");

        User user = userService.selectUserByWxId(null, wxuser.getUnionid());

        List<ByUserTrolleyBvo> list = new ArrayList<ByUserTrolleyBvo>();

        if (user != null) {
            List<ByUserTrolley> byUserTrolleys = userService.selectTrolleyListByPage(user.getId(), 0, Integer.MAX_VALUE);
//        int total = userService.selectTrolleyListCount(user.getId());


            if (byUserTrolleys != null && byUserTrolleys.size() > 0) {
                for (ByUserTrolley current : byUserTrolleys) {
                    ByUserTrolleyBvo bvo = ByUserTrolleyBvo.copyFromByUserTrolley(current);
                    bvo.setProduct(userService.findBizProduct(bvo.getProductId()));
                    bvo.setUser(userService.selectUserById(bvo.getProduct().getUserId()));

                    list.add(bvo);
                }
            }
        }

        model.addAttribute("trolleyList", list);
        model.addAttribute("code", code);

        return PREFIX + "trolley";
    }

    @RequestMapping(value = "/deleteTrolley")
    public String deleteTrolley(@RequestParam(value = "trolley_id",required = false) Integer trolley_id,
                                @RequestParam(value = "code",required = false) String code,
                                Model model) {

        if (trolley_id != null && trolley_id > 0) {
            userService.deleteTrolley(trolley_id);
        }

        return "redirect:"+PREFIX + "/trolley?code="+code;
    }


    //立即购买
    @RequestMapping(value = "/addDirectBuy")
    public String addDirectBuy(@RequestParam(value = "user_id",required = false) Integer user_id,
                               @RequestParam(value = "product_id",required = false) Integer product_id,
                               @RequestParam(value = "biz_user_id",required = false) Integer biz_user_id,
                               @RequestParam(value = "schedule_date",required = false) String schedule_date,
                               @RequestParam(value = "dinner_type",required = false) String dinner_type,
                               @RequestParam(value = "amount",defaultValue = "1") Integer amount,
                               @RequestParam(value = "descn",required = false) String descn,
                               @RequestParam(value = "pay_status",required = false) Integer pay_status,
                               Model model) {

//        User user = getCurrentUser();

//        if (biz_user_id == null || biz_user_id < 1 || (biz_user_id.intValue() == user.getId().intValue())){
//            return "";
//        }

        ByUserOrder order = new ByUserOrder();
        if (product_id != null && product_id > 0) {
            ByUserBizProduct byUserBizProduct = userService.findBizProduct(product_id);
            User currentBizUser = userService.selectUserById(biz_user_id);

            order.setUserId(user_id);

            order.setPayType(PayType.WECHAT_PAY.getCode());
            order.setPayStatus(OrderPayStatus.NOT_PAY.getCode());
            order.setBizUserId(biz_user_id);
            order.setDescn(descn);
            order.setCreateTime(new DateTime());
            order.setUpdateTime(new DateTime());

            BigDecimal orderPrice = BigDecimal.ZERO;


            //更新订单价格
            if(amount == null || amount < 1){
                amount = 1;
            }

            order.setPrice(byUserBizProduct.getCurrentPrice().multiply(new BigDecimal(amount)));
            if (currentBizUser.getBizWorkType().intValue() == 1){ //策划师
                order.setStatus(OrderStatus.NEW_ORDER.getCode());
            }else{
                order.setStatus(OrderStatus.VERIFY_ORDER.getCode());
            }

            if (pay_status.intValue() == OrderPayStatus.PAY_ALL.getCode()) {
                order.setDeposit(order.getPrice());
                order.setNeedPayPrice(BigDecimal.ZERO);
            }else{
                order.setDeposit(Constants.PRODUCT_DEPOSIT_RATIO.multiply(order.getPrice()));
                order.setNeedPayPrice(order.getPrice().subtract(order.getDeposit()));
            }

            userOrderService.insertByUserOrder(order);


            //insert order detail

            ByUserOrderDetail detail = new ByUserOrderDetail();
            detail.setOrderId(order.getId());
            detail.setUserId(user_id);
            detail.setProductId(product_id);
            detail.setAmount(amount);
            detail.setPrice(order.getPrice());

            detail.setScheduleDate(DateUtil.getDateTime(schedule_date));
            detail.setDinnerType(dinner_type);
            detail.setBizUserId(byUserBizProduct.getUserId());
            detail.setOrderId(order.getId());
            detail.setDeposit(Constants.PRODUCT_DEPOSIT_RATIO.multiply(detail.getPrice()));
            detail.setCreateTime(new DateTime());
            detail.setUpdateTime(new DateTime());
            userOrderService.insertByUserOrderDetail(detail);

            //add Schedule
            ByUserBizSchedule byUserBizSchedule = new ByUserBizSchedule();
            byUserBizSchedule.setUserId(biz_user_id);
            byUserBizSchedule.setScheduleDate(detail.getScheduleDate());
            byUserBizSchedule.setStatus(BaseState.NORMAL.getCode());
            byUserBizSchedule.setScheduleType(ScheduleType.getByName(detail.getDinnerType()).getCode());
            byUserBizSchedule.setOrderBy(detail.getUserId());
            byUserBizSchedule.setCreateTime(new DateTime());
            byUserBizSchedule.setUpdateTime(new DateTime());

            userOrderService.insertSchedule(byUserBizSchedule);

        }

        return "redirect:"+ PREFIX + "wxPay_auth?order_id="+order.getId()+"&pay_status="+pay_status;
    }

    //for user use
    @RequestMapping(value = "/orderChangeStatus")
    public String orderChangeStatus(@RequestParam(value = "order_id", required = true) Integer order_id,
                                    @RequestParam(value = "status", required = true) Integer status,
                                    Model model) {
        if (order_id != null && status != null){
            User user = getCurrentUser();

            ByUserOrder order = userOrderService.findByUserOrder(order_id);

            if (user.getId().intValue() == order.getUserId().intValue()) {

                order.setStatus(status);
                order.setUpdateTime(new DateTime());

                userOrderService.insertByUserOrder(order);

                if (status == OrderStatus.CONFIRM_ORDER.getCode()){
                    User bizUser = userService.selectUserById(order.getBizUserId());

                    if (bizUser.getBizDealCount() != null && bizUser.getBizDealCount() > 0) {
                        bizUser.setBizDealCount(bizUser.getBizDealCount() + 1);
                    }else{
                        bizUser.setBizDealCount(1);
                    }

                    BigDecimal commission = BigDecimal.ZERO;

                    if (order.getPayStatus().intValue() == OrderPayStatus.PAY_ALL.getCode()){
                        commission = order.getPrice().multiply(BigDecimal.ONE.subtract(Constants.BIZ_USER_COMMISSION_RATIO));
                    }else if(order.getPayStatus().intValue() == OrderPayStatus.PAY_DEPOSIT.getCode()){
                        commission = order.getDeposit().subtract(order.getPrice().multiply(Constants.BIZ_USER_COMMISSION_RATIO));
                    }

                    if (bizUser.getMoney() == null || bizUser.getMoney() == BigDecimal.ZERO) {
                        bizUser.setMoney(commission);
                    }else{
                        bizUser.setMoney(bizUser.getMoney().add(commission));
                    }
                    writeMoneyLog(bizUser, MoneyType.PAY_ORDER.getCode(), commission);
                    userService.updateUser(bizUser);
                }else if (status == OrderStatus.CANCEL_NOT_REFUND.getCode()){
                    //恢复档期
                    userOrderService.deleteScheduleByOrderId(order_id);
                }
            }
        }

        return PREFIX + "myOrder";
    }

    @RequestMapping(value = "/wxPay_auth")
    public String wxPay_auth(@RequestParam(value = "order_id", required = false) Integer order_id,
                             @RequestParam(value = "pay_status", required = false) Integer pay_status,
                             Model model) {

        return "redirect:"+SnsAPI.connectOauth2Authorize(WeixinUtil.appId, "http://www.boyi028.com/weixin/wxPay", true, order_id+"_"+pay_status);

    }

    @RequestMapping(value = "/wxPay")
    public String wxPay(@RequestParam(value = "code", required = false) String code,
                        @RequestParam(value = "state", required = false) String state,
                       HttpServletRequest request,
                       HttpServletResponse response,
                       Model model) {


        //payPackage 的商品信息,openid 可以通过sns,或事件获取。
        String tmpArr[] = state.split("_");
        Integer order_id = Integer.valueOf(tmpArr[0]);
        Integer pay_status = Integer.valueOf(tmpArr[1]);

        log.debug("订单编号:"+order_id);
        log.debug("支付状态:"+pay_status);

        if (StringUtils.isBlank(code) || order_id == null){
            return null;
        }

        SnsToken snsToken = SnsAPI.oauth2AccessToken(WeixinUtil.appId, WeixinUtil.appSecret, code);

//        weixin.popular.bean.user.User wxuser = SnsAPI.userinfo(snsToken.getAccess_token(), snsToken.getOpenid(), "zh_CN");
        ByUserOrder byUserOrder = userOrderService.findByUserOrder(order_id);


        Unifiedorder unifiedorder = new Unifiedorder();
        unifiedorder.setAppid(Constant.WX_APPID);
        unifiedorder.setMch_id(Constant.WX_MCH_ID);
        unifiedorder.setNonce_str(UUID.randomUUID().toString().toString().replace("-", ""));

        unifiedorder.setOpenid(snsToken.getOpenid());
        unifiedorder.setBody("order_"+order_id);
        unifiedorder.setOut_trade_no(""+order_id);

        if (byUserOrder != null){
            if (pay_status.intValue() == OrderPayStatus.PAY_DEPOSIT.getCode()){
                unifiedorder.setTotal_fee(""+byUserOrder.getDeposit().multiply(new BigDecimal(100)).intValue());
            }else{
                unifiedorder.setTotal_fee(""+byUserOrder.getPrice().multiply(new BigDecimal(100)).intValue());
            }
        }

        Detail detail = new Detail();
        detail.setCost_price(Integer.valueOf(unifiedorder.getTotal_fee()));

        unifiedorder.setDetail(detail);

        unifiedorder.setSpbill_create_ip(request.getRemoteAddr());//IP
        unifiedorder.setNotify_url("http://www.boyi028.com/weixin/notify");
        unifiedorder.setTrade_type("JSAPI");//JSAPI，NATIVE，APP，WAP

        //打印调试信息
        Map tmpmap = MapUtil.objectToMap(unifiedorder, new String[0]);
        if(tmpmap.containsKey("detail")) {
            tmpmap.put("detail", JsonUtil.toJSONString(unifiedorder.getDetail()));
        }
        log.debug("微信支付tmpmap:"+tmpmap.toString());

        Map tmap = MapUtil.order(tmpmap);
        log.debug("微信支付tmpmap1:"+tmap.toString());

        if(tmap.containsKey("sign")) {
            tmap.remove("sign");
        }
        log.debug("微信支付tmpmap2:"+tmap.toString());

        String str = MapUtil.mapJoin(tmap, false, false);

        log.debug("微信支付str:"+str);

        log.debug("微信支付unifiedorderXML:"+SignatureUtil.generateSign(tmpmap, unifiedorder.getSign_type(), Constant.WX_API));




        //统一下单，生成预支付订单
        UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder,Constant.WX_API);

        log.debug("微信支付结果:"+unifiedorderResult.getSign_status());

        //@since 2.8.5  API返回数据签名验证
        if(unifiedorderResult.getSign_status() !=null && unifiedorderResult.getSign_status()){
            String json = PayUtil.generateMchPayJsRequestJson(unifiedorderResult.getPrepay_id(), Constant.WX_APPID, Constant.WX_API);

            model.addAttribute("json", json);
            log.debug("微信支付json:"+json);
            //将json 传到jsp 页面
//            request.setAttribute("json", json);
            //示例jsp
//            request.getRequestDispatcher("pay_example.jsp").forward(request,response);

            return PREFIX +"wx_pay";
        }
        return null;
    }

    @RequestMapping(value = "/notify")
    public String notify(HttpServletRequest request,
                         HttpServletResponse response,
                         Model model) {

        ByUserOrder byUserOrder = null;
        try{
            //获取请求数据
            String xmlData = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8"));
            //将XML转为MAP,确保所有字段都参与签名验证
            Map<String,String> mapData = XMLConverUtil.convertToMap(xmlData);
            //转换数据对象
            MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class,xmlData);

            byUserOrder = userOrderService.findByUserOrder(Integer.valueOf(payNotify.getOut_trade_no()));

            //已处理 去重
            if(expireKey.exists(payNotify.getTransaction_id())){
                MchBaseResult baseResult = new MchBaseResult();
                baseResult.setReturn_code("SUCCESS");
                baseResult.setReturn_msg("OK");
                response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
                return PREFIX +"order_detail?order_id="+byUserOrder.getId();
            }
            //签名验证
            if(SignatureUtil.validateSign(mapData,Constant.WX_API)){
                //@since 2.8.5
                payNotify.buildDynamicField(mapData);

                expireKey.add(payNotify.getTransaction_id());
                MchBaseResult baseResult = new MchBaseResult();
                baseResult.setReturn_code("SUCCESS");
                baseResult.setReturn_msg("OK");
//                response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());

                byUserOrder.setWeixinissubscribe(payNotify.getSub_is_subscribe());
                byUserOrder.setWeixincashfeetype(payNotify.getCash_fee_type());
                byUserOrder.setWeixinbanktype(payNotify.getBank_type());
                byUserOrder.setWeixincashfee(payNotify.getCash_fee());
                byUserOrder.setWeixinorderid(payNotify.getOut_trade_no());
                byUserOrder.setWeixinsign(payNotify.getSign());
                byUserOrder.setWeixinopenid(payNotify.getOpenid());
                byUserOrder.setWeixintradetype(payNotify.getTrade_type());
                byUserOrder.setWeixintimer(payNotify.getTime_end());
                byUserOrder.setWeixinfeetype(payNotify.getFee_type());

                byUserOrder.setNeedPayPrice(byUserOrder.getPrice().subtract(new BigDecimal(payNotify.getTotal_fee()).divide(new BigDecimal(100))));

                if (byUserOrder.getPrice().compareTo(new BigDecimal(payNotify.getTotal_fee()).divide(new BigDecimal(100))) == 0){
                    byUserOrder.setPayStatus(OrderPayStatus.PAY_ALL.getCode());
                }else {
                    byUserOrder.setPayStatus(OrderPayStatus.PAY_DEPOSIT.getCode());

                    //send msg
                    User bizUser = userService.selectUserById(byUserOrder.getBizUserId());
                    Map<String, Object> map = new LinkedHashMap<String, Object>();
                    map.put("code", ""+byUserOrder.getStatus());

                    if (bizUser != null && StringUtils.isNotBlank(bizUser.getMobile()) && bizUser.getBizWorkType() != null && bizUser.getBizWorkType().intValue() != 1) {
                        CommonUtil.sendMessage(bizUser.getMobile(), JSONObject
                                .fromObject(map).toString(), ConfigUtil
                                .getSms_template_code_new_order());
                    }
                }

                userOrderService.insertByUserOrder(byUserOrder);
            }else{
                MchBaseResult baseResult = new MchBaseResult();
                baseResult.setReturn_code("FAIL");
                baseResult.setReturn_msg("ERROR");
//                response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
            }
        }catch (Exception ex){

        }

        return PREFIX +"order_detail?order_id="+byUserOrder.getId();

    }


}

